package com.cheetah.support.redis;

import com.cheetah.config.Redis;
import com.cheetah.config.RedisConfig;
import com.cheetah.support.ConfigHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.yaml.snakeyaml.Yaml;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
@Order(Ordered.LOWEST_PRECEDENCE)
public class RedisBeanDefinitionRegistryPostProcessor
		implements BeanDefinitionRegistryPostProcessor, EnvironmentAware {

    public static final String REDIS = "REDIS_";
    private Environment environment;

	private RedisConfig redisConfig = new RedisConfig();

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
			throws BeansException {

        //定义mongo动态注入redis定义
        //构造bean定义
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
                .genericBeanDefinition(RedisClient.class);
        //设置依赖
        //beanDefinitionBuilder.addPropertyReference();
        BeanDefinition beanDefinition = beanDefinitionBuilder
                .getRawBeanDefinition();
        redisConfig.getRedisMap().forEach((k, v) -> {
            registry.registerBeanDefinition(REDIS + k, beanDefinition);
        });

	}

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
			throws BeansException {

        //注册mongo实例，使用方式可以直接Autowired注入，由于可能注入多个实例，变量名必须使用对应实例名，并且包含REDIS_前缀
        //或者使用Qualifier指定对应bean name
        redisConfig.getRedisMap().forEach((k,v) -> {
            BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
                    .genericBeanDefinition(RedisClient.class, () -> {
                        return new RedisClient(RedisTemplateProcessor.getRedisTemplate(v));
                    });
            BeanDefinition beanDefinition = beanDefinitionBuilder
                    .getRawBeanDefinition();
            ((DefaultListableBeanFactory) beanFactory)
                    .registerBeanDefinition(REDIS + k, beanDefinition);
        });
	}


	@Override
	public void setEnvironment(Environment environment) {
		this.environment = environment;

		String property = environment.getProperty("spring.config.location");
		Yaml yaml = new Yaml();
		FileInputStream in = null;
		try {
			if(property == null){
				return;
			}

			in = new FileInputStream(property);
			Map map = yaml.loadAs(in,HashMap.class);
            ConfigHandler configHandler = new ConfigHandler();
			redisConfig.setRedisMap(configHandler.handleConfig(map,"redis.redisMap", Redis.class));
		} catch (FileNotFoundException e) {
			log.error(e.getMessage(),e);
		}finally {
			if(in != null){
				try {
					in.close();
				} catch (IOException e) {
					log.error(e.getMessage(),e);
				}
			}
		}
	}
}